package cn.edu.scau.cmi.crawler.service;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import org.apache.poi.ss.formula.CacheAreaEval;
import org.aspectj.weaver.ast.Var;
import org.hibernate.id.enhanced.TableStructure;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.edu.scau.cmi.ema.controller.base.CmiEmaController;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.base.EntityFactoryService;
import cn.edu.scau.cmi.ema.util.CmiHibernateProxyUtil;
import cn.edu.scau.cmi.ema.util.CmiSetUtil;
import cn.edu.scau.cmi.ema.util.CmiTimeUtil;
import cn.edu.scau.cmi.front.dao.CmiFoodDAO;

@Service
public class ZhangwenzhongEventImportServiceImpl extends CmiEmaController implements ZhangwenzhongEventImportService{
	
	@Autowired EntityFactoryService entityFactory;
	@Autowired CmiFoodDAO cmiFoodDAO;
	
	@Override
	public boolean importEvent(Event9zwz event9zwz) {
//	为了提高效率，没有food的事件不保存，免得初始化event浪费时间
		
//		（0）先检测food，如果food不合适，就不用继续下面的步骤了。
		Food food = buildFood(event9zwz);
		if(food == null) {
			System.out.println("Event的Food是空，该数据没有意义");
			event9zwz.setImported(false);//没有导入
			event9zwzService.saveEvent9zwz(event9zwz);
			return false;
		}
		
		Subject subject = buildSubject(event9zwz);
		if(subject == null) {
			System.out.println("导入Event的主体不能为空，这一行记录没有被保存");
			event9zwz.setDescription("导入Event的主体不能为空，这一行记录没有被保存");
			return false;
		}else if(subject.getId() == null) {
			subject = subjectService.saveSubject(subject);
		}
		
//		foodbatch: foodtype -> food -> foodbatchfiller -> detect -> foodbatch.
		Foodtype foodtype = buildFoodtype(event9zwz);
		if(foodtype == null) {
			foodtype = foodtypeDAO.findFoodtypeById(-2);
		}
		

//		暂时不修改食物类型	
		food.setFoodtype(foodtype);
//		这里有缺陷，如果只是修改了foodtye，保存的时候会重新生产一条记录
		
		food = foodDAO.store(food);
		foodDAO.flush();
//		food = foodService.saveFood(food);
		
		
//		（1）初始化event。
		Event event = entityFactory.initEvent();
		
//		（2） 设置默认基本属性
		event.setAuditTime(Calendar.getInstance());
		event.setName(event9zwz.getName());
		event.setDescription(event9zwz.getDescription());
		
		event.setAuditor(CmiSetUtil.getFirstInstance(userDAO.findUserByName("张文众")));
//		（3）设置基本属性和引用属性
		
//		张老师的时间数据很奇怪，有一部分是正常的
		//有一部分是数字
		
		int i = event9zwz.getDiscoverydetailtime().indexOf('-');
		if(i>0) {
			event.setDiscoveryTime(CmiTimeUtil.getYMDCalendar(event9zwz.getDiscoverydetailtime()));
		}else {
			String[] discoveryTimesString =  event9zwz.getDiscoverydetailtime().split("/");
			if(discoveryTimesString.length > 1) {
				event.setDiscoveryTime(CmiTimeUtil.getYMDCalendar(discoveryTimesString[0] + "-" + discoveryTimesString[1] + "-" + discoveryTimesString[2]));
			}else {
				event.setDiscoveryTime(CmiTimeUtil.castZwzDateString2Calendar(event9zwz.getDiscoverydetailtime()));
			}
		}
		
		Address discoveryAddress = buildDiscoveryAddress(event9zwz);
		event.setDiscoveryAddress(discoveryAddress);
		
		Address sourceAddress = buildSourceAddress(event9zwz);
		event.setSourceAddress(sourceAddress);
		
		event.setSubject(subject);
		
//		信息来源：repoortor source，用户，也可以是抽象的用户，例如，市场监管
		User reportor = buildReportor(event9zwz);
		event.setReportor(reportor);
		
		Url url = buildUrl(event9zwz);
		event.setUrl(url);
		
//		（4）设置被引用属性，有多个法律
		
//		Law law = buildLaw(event9zwz);
		Set<Law> laws = buildLaws(event9zwz);
		if(laws !=null) {
			event.setLawsForEvent(laws);
		}
		
//		------T列 张老师的数据中只有一个掺假环节
		Adulterlink adulterlink = buildAdulterlink(event9zwz);//
		Eventadulterlink eventadulterlink = entityFactory.initEventadulterlink();
		
		eventadulterlink.setAdulterlink(adulterlink);
		eventadulterlink.setName(event9zwz.getName() + "的掺假环节");
		eventadulterlink = eventadulterlinkService.saveEventadulterlink(eventadulterlink);
		
//		?????
		Set<Eventadulterlink> eventadulterlinks = new HashSet<Eventadulterlink>();
		eventadulterlinks.add(eventadulterlink);
		event.setEventadulterlinksForEvent(eventadulterlinks);
		
		Set<Adultertype> adultertypes = buildAdultertype(event9zwz);
		event.setAdultertypesForEvent(adultertypes);
		
		Discoverylink discoverylink = buildDiscoverylink(event9zwz);
		Set<Discoverylink> discoverylinks = new HashSet<Discoverylink>();
		if(discoverylink != null) {
			discoverylinks.add(discoverylink);
		}
		event.setDiscoverylinksForEvent(discoverylinks);


//		------S列：掺假物质
		Set<Foodbatchfiller> foodbatchfillers = buildFoodbatchfiller(event9zwz);
		
		Detectmethod detectmethod = buildDetectmethod(event9zwz);
		
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		foodbatch.setFood(food);
		foodbatch.setUnit(unitDAO.findUnitById(-2));
		foodbatch.setFoodbatchfillersForFoodbatch(foodbatchfillers);
//		TODO !!!!!!日期需要修改，暂时使用当前的值
		Calendar date = Calendar.getInstance();
		foodbatch.setDate(date );
		foodbatch.setDetectmethod(detectmethod);
		foodbatch.setName(event.getSubject().getName() + event.getName() + "的食物批次");
		foodbatch = foodbatchService.saveFoodbatch(foodbatch);
		
		event.setSourceTime(null);
		event.setCrawlTime(null);
		event.setSubject(subject);
		event.setFoodbatch(foodbatch);
		
		event = eventService.saveEvent(event);
		System.out.println("事件名称：" + event.getName() + "，事件地址" + event.getSourceAddress() + "，事件");

		
//		保存依赖event的数据
		Eventpunish eventpunish = buildEventpunish(event9zwz);//描述中被封装了。其他属性这里封装
		if(eventpunish !=null) {
			eventpunish.setName(event.getName() + "的处罚");
			eventpunish.setDate(Calendar.getInstance());//date不能为空
			eventpunish.setPunish(punishDAO.findPunishById(-2));
			eventpunish.setEvent(event);
			eventpunish = eventpunishService.saveEventpunish(eventpunish);
		}
		
		event9zwz.setImported(true);
//		event9zwzService.deleteEvent9zwz(event9zwz);
//		event9zwzService.saveEvent9zwz(event9zwz);
		
//		如果还没有删除，就删除
//		event = eventService.saveEvent(event);
		
		try {
			event9zwzService.deleteEvent9zwz(event9zwz);
		}catch(Exception e) {
			System.out.println(e);
		}
		return true;
	}
	
//	检测特征就是掺假的物质，是一个集合
	private Set<Feature> buildFeature(Set<Foodbatchfiller> foodbatchfillers) {
		Feature feature = entityFactory.initFeature();
		Set<Feature> features = new HashSet<Feature>();
		
		
//		掺假
		for(Foodbatchfiller foodbatchfiller : foodbatchfillers) {
			Set<Feature> fs = featureDAO.findFeatureByName(foodbatchfiller.getName());
			if(fs.size() > 0) {
				features.add(CmiSetUtil.getLastInstance(fs));
			}
		}
		return features;
	}

//	如果能获取处罚，不添加了。这个是类型。
	private Punish buildPunish(Event9zwz event9zwz) {
		Punish punish = punishDAO.findPunishById(-2);
		String punishString = event9zwz.getEffect();
		
		if(punishString ==null) {
			return null;
		}
		
		Set<Punish> punishs = punishDAO.findPunishByName(punishString);
		
		if(punishs.size() > 0) {
			punish = CmiSetUtil.getLastInstance(punishs);
		}

		return null;
	}


	private User buildReportor(Event9zwz event9zwz) {
		User user = entityFactory.initUser();
//		来源是用户，可以包含监管机构、媒体报道等这种抽象的用户。
		Set<User> users = userDAO.findUserByName(event9zwz.getSource());
		if(users.size() > 0) {
			user = CmiSetUtil.getLastInstance(users);
		}else {
			user.setName(event9zwz.getSource());
			user.setUsername(event9zwz.getSource());
			user.setPassword("askfj屁哦qej;askdfjpij;nvaeriifjwertjmdsgfwqert234");
			user = userService.saveUser(user);
		}
		return user;
	}


//	
	private Set<Law> buildLaws(Event9zwz event9zwz) {
		Set<Law> laws = new HashSet<Law>();
		String lawsString = event9zwz.getLaw();	
		if(lawsString == null || lawsString.trim().equals("")) {
			return null;
		}
		
		String[] lawStrings = lawsString.split("、");
		for(int i = 0; i< lawStrings.length; i++) {
			Set<Law> ls = lawDAO.findLawByName(lawStrings[i]);
			if(ls.size() <1) {
				
				Law law = entityFactory.initLaw();
				law.setName(lawStrings[i]);
				law = lawService.saveLaw(law);
				laws.add(law);
			}else {
				laws.addAll(ls);
			}
		}
		return laws;
	}

	private Detectmethod buildDetectmethod(Event9zwz event9zwz) {
			Detectmethod detectmethod = entityFactory.initDetectmethod(); 
			String detectmethodName = event9zwz.getDetectmethod();
			
			if(detectmethodName == null) {
				return null;
			}
			
			Set<Detectmethod> detectmethods = detectmethodDAO.findDetectmethodByName(detectmethodName.trim());
			if(detectmethods.size() > 0) {
				detectmethod = CmiSetUtil.getLastInstance(detectmethods);
			}else {
				detectmethod.setName(detectmethodName.trim());
				detectmethod.setStep("");
				
				detectmethod = detectmethodService.saveDetectmethod(detectmethod);
			}
			return detectmethod;
		}

//	如果环节名称是空，返回id是-2的数据，如果没有找到就新建一个数据
	private Discoverylink buildDiscoverylink(Event9zwz event9zwz) {
		Discoverylink discoverylink = entityFactory.initDiscoverylink();
		
		String discoverylinkString = event9zwz.getDiscoverylink();
		if (discoverylinkString == null) {
			return discoverylinkDAO.findDiscoverylinkById(-2); 
		}
		
		Set<Discoverylink> discoverylinks = discoverylinkDAO.findDiscoverylinkByName(event9zwz.getDiscoverylink());
		if(discoverylinks.size() > 0) {
			discoverylink = CmiSetUtil.getLastInstance(discoverylinks);
		}else {
			discoverylink.setName(event9zwz.getDiscoverylink());
			discoverylink = discoverylinkService.saveDiscoverylink(discoverylink);
		}
		return discoverylink;
	}

//	掺假物质，filler没有的掺假需要添加到数据库中
	private Set<Foodbatchfiller> buildFoodbatchfiller(Event9zwz event9zwz) {
		Set<Foodbatchfiller> foodbatchfillers = new HashSet<Foodbatchfiller>();
		
		String foodbatcherfillerString = event9zwz.getFoodbatchfiller();
		if(foodbatcherfillerString == null) {
			return null;
		}

		String[] foodbatcherfillerStrings = foodbatcherfillerString.split("、");
//		猪肉、牛肉
		for(int i = 0; i< foodbatcherfillerStrings.length; i++) {
			Set<Foodbatchfiller> fs = foodbatchfillerDAO.findFoodbatchfillerByName(foodbatcherfillerStrings[i]);
			if(fs.size() == 0) {
				Foodbatchfiller f = entityFactory.initFoodbatchfiller();
				f.setName(foodbatcherfillerStrings[i]);
				f = foodbatchfillerService.saveFoodbatchfiller(f);
				fs.add(f);
			}
			
			foodbatchfillers.addAll(foodbatchfillers);
		}
		return foodbatchfillers;
	}

	private Set<Adultertype> buildAdultertype(Event9zwz event9zwz) {
		Set<Adultertype> adultertype = new HashSet<Adultertype>();
		
		String[] adultertypesString =  event9zwz.getAdultertype().split("、");
		for(String adultertypeString : adultertypesString) {
			adultertype.addAll(adultertypeDAO.findAdultertypeByName(adultertypeString));
		}
		if(adultertype.size()<1) {
			adultertype.add(adultertypeDAO.findAdultertypeById(-2));
		}
		
		return adultertype;
	}

//	掺假环节 -> eventadultertype
	private Adulterlink buildAdulterlink(Event9zwz event9zwz) {
		Adulterlink adulterlink = entityFactory.initAdulterlink();
//		不能自己添加掺假类型
		String adulterlinkName = event9zwz.getAdulterlink();
		
		Set<Adulterlink> adulterlinks = adulterlinkDAO.findAdulterlinkByName(adulterlinkName);
		if(adulterlinks.size() == 0) {
			adulterlink = adulterlinkDAO.findAdulterlinkById(-2);
		}else {
			adulterlink = CmiSetUtil.getLastInstance(adulterlinks);
		}
		return adulterlink;
	}

	private Eventpunish buildEventpunish(Event9zwz event9zwz) {
		Eventpunish eventpunish = null;
		String eventpunishString = event9zwz.getEffect();
		if(eventpunishString ==null || eventpunishString.trim().equals("")) {
			return eventpunish;
		}
		
		eventpunish = entityFactory.initEventpunish();
		eventpunish.setDescription(event9zwz.getEffect());
		return eventpunish;
	}

	private Url buildUrl(Event9zwz event9zwz) {
		
		Set<Url> urls = urlDAO.findUrlByName(event9zwz.getUrl());
		Url url = entityFactory.initUri();
		if(urls.size() > 0) {
			url = CmiSetUtil.getLastInstance(urls);
		}else {
			url.setName(event9zwz.getUrl());
			url.setValue(event9zwz.getUrl());
			url = urlService.saveUrl(url);
		}
		return url;
	}

	private Address buildDiscoveryAddress(Event9zwz event9zwz) {
//		有省、市、县地址，先找县，再找市，再找省
		Set<Address> countyAddresss = addressDAO.findAddressByName(event9zwz.getDiscoverycounty());
		if(countyAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(countyAddresss);
		}
		
		Set<Address> districtAddresss = addressDAO.findAddressByName(event9zwz.getDiscoverydistrict());
		if(districtAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(districtAddresss);
		}
		
		Set<Address> provinceAddresss = addressDAO.findAddressByName(event9zwz.getDiscoveryprovince());
		if(provinceAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(provinceAddresss);
		}
		return addressDAO.findAddressById(-2);
	}
	
	private Address buildSourceAddress(Event9zwz event9zwz) {
//		有省、市、县地址，先找县，再找市，再找省
		Set<Address> countyAddresss = addressDAO.findAddressByName(event9zwz.getSourcecounty());
		if(countyAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(countyAddresss);
		}
		
		Set<Address> districtAddresss = addressDAO.findAddressByName(event9zwz.getSourcedistrict());
		if(districtAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(districtAddresss);
		}
		
		Set<Address> provinceAddresss = addressDAO.findAddressByName(event9zwz.getSourceprovince());
		if(provinceAddresss.size()>0) {
			return CmiSetUtil.getLastInstance(provinceAddresss);
		}
		return addressDAO.findAddressById(-2);
	}
	
	private Detect buildDetect(Event9zwz crawlerevent) {
		Detect detect = entityFactory.initDetect();
		return detect;
	}

	private Detectdetail buildDetectdetail(Event9zwz enent9zwz) {
		Detectdetail instance = entityFactory.initDetectdetail();//CmiSetUtil.getSoleInstance(detectdetailDAO.findDetectdetailByName(enent9zwz.getDetectdetail()));
		return instance;
	}


//	没有食物批次，对每一个事件创建一个只适用于链接的食物。食物批次添加一个是否真实的食物批次。
	private Foodbatch buildFoodbatch(Event9zwz enent9xls) {
		Foodbatch foodbatch = entityFactory.initFoodbatch();
		return foodbatch;
	}

	private Food buildFood(Event9zwz event9xls) {
//	先检测是否由名称，如果没有名称，就返回。		
		String foodName = event9xls.getFood();
		if(foodName == null || foodName.trim().equals("")) {
			return null;
		}
		Food food = entityFactory.initFood();
		
		Set<Food> foodsByName = new HashSet<Food>();
		String producerName = event9xls.getProducer();
		
		Producer producer = null;
//		食物名称不为空，
		if(!( producerName == null || producerName.trim().equals(""))) {
//			生产商名称唯一
			Set<Producer> producers = producerDAO.findProducerByName(event9xls.getProducer());
			if(producers.size()>0) {
				producer = CmiSetUtil.getFirstInstance(producers);
//				查看数据库中是否已经存在foodName 和 producer的食物，如果没有，就新建，否则就返回这个食物
				
				Set<Food> fs = cmiFoodDAO.findFoodsByNameAndProducer(foodName, producerName);
				
				if(fs.size() > 0) {
					food = CmiSetUtil.getFirstInstance(fs);
					return food;
				}
				food.setName(foodName);
				food.setProducer(producer);				
				food = foodService.saveFood(food);
				return food;
				
			}else {
//				数据库中还没有生产厂商，那么食物+生产厂商的这个食物还没有，就需要建立food记录。
				producer = entityFactory.initProducer();
				producer.setName(producerName);
				producer = producerService.saveProducer(producer);
				
				food.setName(foodName);
				food.setProducer(producer);
				food = foodService.saveFood(food);
				return food;
			}
		}else {
//			没有生产厂商，根据食物名称和来源地址查找食物，如果找到，就返回，如果没有找到，就新建
//			食物名称查找食物，可能有多个，对每一个进行地址匹配，
			foodsByName = foodDAO.findFoodByName(foodName);
			if(foodsByName.size() == 0) {
				food.setName(foodName);
				food = foodService.saveFood(food);
//				食物名称都还没有的话，食物的批次就没有意义。
//				暂时保存这个食物，然后再次确定是否有相关地址，在保存事件后再修改食物				
				
				return food;
			}			
//			通过食物名称查找到了食物，然后看这些食物有哪些食物批次，有哪些事件，
//			事件的来源地址是张文众老师的事件的来源地址，那么这个食物就是找到的食物
//			如果没有找到，就判断是否是发现地址，
//			如果都不是，那么就新建食物
			for (Food foodByName : foodsByName) {
//				每一个食物可能有多个食物批次
//				发现的问题，这里懒加载了。刚才保存进去的数据没有重新获取？？？？？？
//				暂时再查一次，使用懒加载的方式也不行
//				Set<Foodbatch> foodbatchs = foodByName.getFoodbatchsForFood();
				
//				Food fs = foodDAO.findFoodById(foodByName.getId());
//				Set<Foodbatch> fbs = fs.getFoodbatchsForFood();
//				Food test = CmiHibernateProxyUtil.deproxy(foodDAO.findFoodById(foodByName.getId()));
				
//				Set<Foodbatch> foodbatchs = foodDAO.findFoodById(foodByName.getId()).getFoodbatchsForFood();
				
				Set<Foodbatch> foodbatchs = foodbatchDAO.findFoodbatchsByFood(foodByName.getId(), -1, -1);
				
				for (Foodbatch foodbatch : foodbatchs) {
//					每个食物批次有多个事件，同样的道理，不能正确获取foodbtach的事件，使用eventDAO解决，后期看怎么办理
//					Set<Event> events = foodbatch.getEventsForFoodbatch();
					Set<Event> events = eventDAO.findEventsByFoodbatch(foodbatch.getId(), -1, -1);
					
					for (Event event : events) {
//						每个事件地址。事件来源地址为空，保持到数据库中是-2；
//						TODO 待解决，纯净水没有厂商、来源地、发现地导致多个food的记录缺陷原因：
//						因为数据库中没有地址用的id为-2的地址代替，而电子表格中是空字符串
						
						String eventSourceAddressName = event.getSourceAddress().getName();
						String eventDiscoveryAddressName = event.getDiscoveryAddress().getName();
//						******确定来源地址，
						String xlsSourceAddress = "";
						String xlsCounty = event9xls.getSourcecounty().trim();
						String xlsDistrict = event9xls.getSourcedistrict().trim();
						String xlsProvince = event9xls.getSourceprovince().trim();
						
						if(!xlsCounty.equals("")) {
							xlsSourceAddress = xlsCounty;
						}else if(!xlsDistrict.equals("")) {
							xlsSourceAddress = xlsDistrict;
						}else if(!xlsProvince.equals("")) {
							xlsSourceAddress = xlsProvince;
						}

//						******确定发现地址
						String xlsDiscoveryAddress = "";
						String xlsDiscoveryCounty = event9xls.getDiscoverycounty().trim();
						String xlsDiscoveryDistrict = event9xls.getDiscoverydistrict().trim();
						String xlsDiscoveryProvince = event9xls.getDiscoveryprovince().trim();
						
						if(!xlsDiscoveryCounty.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryCounty;
						}else if(!xlsDiscoveryDistrict.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryDistrict;
						}else if(!xlsDiscoveryProvince.equals("")) {
							xlsDiscoveryAddress = xlsDiscoveryProvince;
						}
	

//						(1) 待入库的事件有来源地址
						if(!xlsSourceAddress.equals("")) {
//							有来源地址
							if(eventSourceAddressName.equals(xlsSourceAddress)) {
								return foodByName;
							}
//						(2) 待入库的事件没有发现地址
						}else {
//							（2.1）待入库的事件有发现地址
							if(!xlsDiscoveryAddress.equals("")) {
								if(eventDiscoveryAddressName.equals(xlsDiscoveryAddress)) {
									return foodByName;
								}
//							（2.2）待入库的事件没有发现地址
							}else {
								if(event.getDiscoveryAddress().getId() == -2) {
									return foodByName;
								}
							}
						}
					}					
				}
			}		
		}
				
	
//		食物初始话的时候，name设置成了""
		if(food.getId()==null) {
//			有可能出现：食物名称相同，因为物理主键的原因，不能保存数据的情况。
			food.setName(foodName);
			food = foodService.saveFood(food);
		}		

		return food;
	}

// 获取精确的类型，如果没有找到就使用著类型，如果都为空，就返回-2的那个类型
	private Foodtype buildFoodtype(Event9zwz enent9zwz) {
		
		Foodtype foodtype = CmiSetUtil.getSoleInstance(foodtypeDAO.findFoodtypeByName(enent9zwz.getFoodsubtype()));
		if(foodtype == null) {
//			食物类型是一个标准数据，不容许擅自保存
			foodtype = CmiSetUtil.getSoleInstance(foodtypeDAO.findFoodtypeByName(enent9zwz.getFoodmaintype()));
			if(foodtype == null) {
				foodtype = foodtypeDAO.findFoodtypeById(-2);
			}
		}
		return foodtype;
	}

	private Subject buildSubject(Event9zwz enent9zwz) {
		if(enent9zwz.getSubject() == null) {
			return null;
		}
		
		Subject instance = CmiSetUtil.getSoleInstance(subjectDAO.findSubjectByName(enent9zwz.getSubject()));
		if(instance == null) {
			instance = entityFactory.initSubject();
			instance.setName(enent9zwz.getSubject());
		}
		
		return instance;
	}
}